﻿#pragma once

#ifndef _TIME_BASE_H_
#define _TIME_BASE_H_


#if defined(_MSC_VER)
//#pragma warning(disable: 4251) // 禁用 dll 接口的警告
#define _CRT_SECURE_NO_WARNINGS // 禁用安全警告
#endif

// C++ 接口
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
// #include <condition_variable>

// C 接口
#include <time.h>


#if defined(_WIN32) || defined(_WIN64)
#include <chrono>
#else
	// 包含 usleep 函数的头文件
#include <unistd.h>
#endif

class TimeBase
{
public:
	TimeBase();
	explicit TimeBase(const std::string& name);
	TimeBase(const TimeBase& other);
	TimeBase(TimeBase&& other) noexcept;
	TimeBase& operator=(const TimeBase& other);
	TimeBase& operator=(TimeBase&& other) noexcept;
	virtual ~TimeBase();

	/// <summary>
	/// 返回经过的时间（以微秒为单位）。
	/// </summary>
	/// <returns>
	/// 自某个参考点（如程序启动）以来经过的毫秒数。
	/// </returns>
	long long elapsed();

	void restart();
	void restart(const std::string& name);

	// 获取当地时间戳，单位为微秒，是从 1900-01-01 00:00:00 UTC 开始的秒数
	static long long now_time();

	/*
	格式化时间戳函数
	@param time_num 时间戳，单位为微秒，是从 1900-01-01 00:00:00 UTC 开始的
	@param format_str 格式化字符串，默认为空，最大 10 毫秒精度
		-- %A 或 %a 表示星期几，如星期一为 "Monday"
		-- 长日期比如 %x年 - %x月 - %x日 %x时:%x分:%x秒:%x毫秒 %A
			格式顺序：年、月、日、时、分、秒、10毫秒 星期几在指定的 %A 或 %a 位置
			默认格式为 "%Y-%m-%d %H:%M:%S.%f %A"
		-- 例：
			格式 %x/%x/%x %A %x时:%x分:%x秒:%x毫秒 可能返回2025/01/01 Monday 01:23:45:67
			格式 %x年%x月%x日 %A 可能返回 2025年01月01日 Monday
		-- 短日期格式默认 %H:%M:%S.%f %A
			没有前面的年月日
		-- 例：
			格式 %H:%M:%S.%f 可能返回 01:23:45.67
			格式 %H时%M分		可能返回 01时23分
	@param long_flag 是否使用长格式，默认 false 表示短格式
	*/
	static const char* format(long long time_num, const char* format_str = "", bool long_flag = false);
	const char* format_start(const char* format_str = "", bool long_flag = false) const;
	const char* format_point(const char* format_str = "", bool long_flag = false) const;

	void reset_name(const std::string& name);
	void set_time_point_now() const;

#if defined(_WIN32) || defined(_WIN64)
	const std::chrono::high_resolution_clock::time_point& get_time_point() const;
#endif

	const long long& time_point_num() const;
	const std::string& get_timer_name() const;

	static void sleep(unsigned long long microseconds);

	static const TimeBase& get_instance(); // 全局记时器
	static const TimeBase& get_instance(const std::string& name);


private:
	std::string program_name = "unknown";
	mutable std::mutex mutex_;
	mutable std::mutex mutex_elapse_;
	std::thread::id thread_id;

#if defined(_WIN32) || defined(_WIN64)
	std::chrono::high_resolution_clock::time_point start_time_chrono;
	std::chrono::high_resolution_clock::time_point time_point_chrono;
#endif
	long long start_time;
	long long time_point;
};

#define format_now_time(format_str, long_flag) TimeBase::format(TimeBase::now_time(), format_str, long_flag)

#endif // _TIME_BASE_H_
